import { TransactionPattern, BehaviorInsight, AnomalyAlert, Transaction, ChainType, Evidence } from '../../types';
import { createModuleLogger } from '../../utils/logger';
import { DatabaseService } from '../database/DatabaseService';
import { AddressLabelService } from '../address/AddressLabelService';

const logger = createModuleLogger('pattern-recognition');

export class PatternRecognitionService {
  private static instance: PatternRecognitionService;
  private dbService: DatabaseService;
  private addressLabelService: AddressLabelService;
  private patternCache = new Map<string, TransactionPattern[]>();

  private constructor(dbService: DatabaseService, addressLabelService: AddressLabelService) {
    this.dbService = dbService;
    this.addressLabelService = addressLabelService;
  }

  public static getInstance(
    dbService: DatabaseService, 
    addressLabelService: AddressLabelService
  ): PatternRecognitionService {
    if (!PatternRecognitionService.instance) {
      PatternRecognitionService.instance = new PatternRecognitionService(dbService, addressLabelService);
    }
    return PatternRecognitionService.instance;
  }

  /**
   * 分析地址的交易模式
   */
  public async analyzeTransactionPatterns(address: string, chain: ChainType): Promise<TransactionPattern[]> {
    try {
      const cacheKey = `${address.toLowerCase()}_${chain}`;
      
      // 检查缓存
      if (this.patternCache.has(cacheKey)) {
        return this.patternCache.get(cacheKey) || [];
      }

      logger.info(`开始分析交易模式: ${address} on ${chain}`);

      // 获取地址的交易历史
      const transactions = await this.dbService.getTransactionsByAddress(address, chain);
      if (transactions.length < 5) {
        logger.debug(`地址 ${address} 交易记录不足，跳过模式分析`);
        return [];
      }

      const patterns: TransactionPattern[] = [];

      // 检测各种交易模式
      patterns.push(...await this.detectDepositWithdrawalPattern(address, transactions));
      patterns.push(...await this.detectDeFiInteractionPattern(address, transactions));
      patterns.push(...await this.detectArbitragePattern(address, transactions));
      patterns.push(...await this.detectAccumulationPattern(address, transactions));
      patterns.push(...await this.detectDistributionPattern(address, transactions));
      patterns.push(...await this.detectAnomalyPattern(address, transactions));

      // 缓存结果
      this.patternCache.set(cacheKey, patterns);
      
      logger.info(`模式分析完成: ${address}, 发现 ${patterns.length} 个模式`);
      return patterns;

    } catch (error) {
      logger.error(`交易模式分析失败 ${address}:`, error);
      return [];
    }
  }

  /**
   * 检测存取款模式
   */
  private async detectDepositWithdrawalPattern(address: string, transactions: any[]): Promise<TransactionPattern[]> {
    const patterns: TransactionPattern[] = [];
    
    // 分析与交易所的交互
    const exchangeTransactions = [];
    for (const tx of transactions) {
      const toLabel = await this.addressLabelService.getAddressLabel(tx.to, tx.chain);
      const fromLabel = await this.addressLabelService.getAddressLabel(tx.from, tx.chain);
      
      if (toLabel?.type === 'exchange' || fromLabel?.type === 'exchange') {
        exchangeTransactions.push({
          ...tx,
          isDeposit: tx.from === address && toLabel?.type === 'exchange',
          isWithdrawal: tx.to === address && fromLabel?.type === 'exchange'
        });
      }
    }

    if (exchangeTransactions.length >= 3) {
      const deposits = exchangeTransactions.filter(tx => tx.isDeposit);
      const withdrawals = exchangeTransactions.filter(tx => tx.isWithdrawal);

      if (deposits.length >= 2) {
        patterns.push({
          id: `deposit_${Date.now()}`,
          type: 'deposit',
          confidence: Math.min(deposits.length / 5, 1),
          description: `频繁向交易所充值，${deposits.length}次充值`,
          frequency: deposits.length,
          avgAmount: deposits.reduce((sum, tx) => sum + tx.valueUSD, 0) / deposits.length,
          timePattern: this.extractTimePattern(deposits),
          relatedAddresses: [...new Set(deposits.map(tx => tx.to))],
          detectedAt: new Date()
        });
      }

      if (withdrawals.length >= 2) {
        patterns.push({
          id: `withdrawal_${Date.now()}`,
          type: 'withdrawal',
          confidence: Math.min(withdrawals.length / 5, 1),
          description: `频繁从交易所提现，${withdrawals.length}次提现`,
          frequency: withdrawals.length,
          avgAmount: withdrawals.reduce((sum, tx) => sum + tx.valueUSD, 0) / withdrawals.length,
          timePattern: this.extractTimePattern(withdrawals),
          relatedAddresses: [...new Set(withdrawals.map(tx => tx.from))],
          detectedAt: new Date()
        });
      }
    }

    return patterns;
  }

  /**
   * 检测DeFi交互模式
   */
  private async detectDeFiInteractionPattern(address: string, transactions: any[]): Promise<TransactionPattern[]> {
    const patterns: TransactionPattern[] = [];
    
    // 分析与DeFi协议的交互
    const defiTransactions = [];
    for (const tx of transactions) {
      const toLabel = await this.addressLabelService.getAddressLabel(tx.to, tx.chain);
      const fromLabel = await this.addressLabelService.getAddressLabel(tx.from, tx.chain);
      
      if (toLabel?.type === 'defi' || fromLabel?.type === 'defi') {
        defiTransactions.push(tx);
      }
    }

    if (defiTransactions.length >= 3) {
      // 分析DeFi协议类型
      const protocolCounts = new Map<string, number>();
      defiTransactions.forEach(tx => {
        const protocol = this.identifyDeFiProtocol(tx.to);
        protocolCounts.set(protocol, (protocolCounts.get(protocol) || 0) + 1);
      });

      const mainProtocol = Array.from(protocolCounts.entries())
        .sort((a, b) => b[1] - a[1])[0];

      patterns.push({
        id: `defi_${Date.now()}`,
        type: 'defi_interaction',
        confidence: Math.min(defiTransactions.length / 10, 1),
        description: `活跃的DeFi用户，主要使用 ${mainProtocol[0]}`,
        frequency: defiTransactions.length,
        avgAmount: defiTransactions.reduce((sum, tx) => sum + tx.valueUSD, 0) / defiTransactions.length,
        timePattern: this.extractTimePattern(defiTransactions),
        relatedAddresses: [...new Set(defiTransactions.map(tx => tx.to))],
        detectedAt: new Date()
      });
    }

    return patterns;
  }

  /**
   * 检测套利模式
   */
  private async detectArbitragePattern(address: string, transactions: any[]): Promise<TransactionPattern[]> {
    const patterns: TransactionPattern[] = [];
    
    // 查找快速买卖模式（短时间内的相反操作）
    const sortedTxs = transactions.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
    const arbitragePairs = [];

    for (let i = 0; i < sortedTxs.length - 1; i++) {
      const tx1 = sortedTxs[i];
      const tx2 = sortedTxs[i + 1];
      
      const timeDiff = new Date(tx2.timestamp).getTime() - new Date(tx1.timestamp).getTime();
      const isQuickSequence = timeDiff < 10 * 60 * 1000; // 10分钟内
      const isSimilarAmount = Math.abs(tx1.valueUSD - tx2.valueUSD) / Math.max(tx1.valueUSD, tx2.valueUSD) < 0.1;
      
      if (isQuickSequence && isSimilarAmount) {
        arbitragePairs.push([tx1, tx2]);
      }
    }

    if (arbitragePairs.length >= 2) {
      patterns.push({
        id: `arbitrage_${Date.now()}`,
        type: 'arbitrage',
        confidence: Math.min(arbitragePairs.length / 5, 1),
        description: `疑似套利行为，${arbitragePairs.length}对快速交易`,
        frequency: arbitragePairs.length,
        avgAmount: arbitragePairs.reduce((sum, pair) => sum + (pair[0].valueUSD + pair[1].valueUSD) / 2, 0) / arbitragePairs.length,
        timePattern: {
          isRegular: false,
          dayOfWeek: [],
          hourOfDay: []
        },
        relatedAddresses: [...new Set(arbitragePairs.flat().map(tx => tx.to))],
        detectedAt: new Date()
      });
    }

    return patterns;
  }

  /**
   * 检测资金聚合模式
   */
  private async detectAccumulationPattern(address: string, transactions: any[]): Promise<TransactionPattern[]> {
    const patterns: TransactionPattern[] = [];
    
    // 分析资金流入情况
    const incomingTxs = transactions.filter(tx => tx.to === address);
    
    if (incomingTxs.length >= 5) {
      // 检查是否来自多个不同地址
      const uniqueSenders = new Set(incomingTxs.map(tx => tx.from));
      
      if (uniqueSenders.size >= 3) {
        const totalInflow = incomingTxs.reduce((sum, tx) => sum + tx.valueUSD, 0);
        const avgAmount = totalInflow / incomingTxs.length;
        
        patterns.push({
          id: `accumulation_${Date.now()}`,
          type: 'accumulation',
          confidence: Math.min(uniqueSenders.size / 10, 1),
          description: `资金聚合地址，从${uniqueSenders.size}个地址接收资金`,
          frequency: incomingTxs.length,
          avgAmount,
          timePattern: this.extractTimePattern(incomingTxs),
          relatedAddresses: Array.from(uniqueSenders),
          detectedAt: new Date()
        });
      }
    }

    return patterns;
  }

  /**
   * 检测资金分散模式
   */
  private async detectDistributionPattern(address: string, transactions: any[]): Promise<TransactionPattern[]> {
    const patterns: TransactionPattern[] = [];
    
    // 分析资金流出情况
    const outgoingTxs = transactions.filter(tx => tx.from === address);
    
    if (outgoingTxs.length >= 5) {
      // 检查是否发送到多个不同地址
      const uniqueRecipients = new Set(outgoingTxs.map(tx => tx.to));
      
      if (uniqueRecipients.size >= 3) {
        const totalOutflow = outgoingTxs.reduce((sum, tx) => sum + tx.valueUSD, 0);
        const avgAmount = totalOutflow / outgoingTxs.length;
        
        patterns.push({
          id: `distribution_${Date.now()}`,
          type: 'distribution',
          confidence: Math.min(uniqueRecipients.size / 10, 1),
          description: `资金分散地址，向${uniqueRecipients.size}个地址发送资金`,
          frequency: outgoingTxs.length,
          avgAmount,
          timePattern: this.extractTimePattern(outgoingTxs),
          relatedAddresses: Array.from(uniqueRecipients),
          detectedAt: new Date()
        });
      }
    }

    return patterns;
  }

  /**
   * 检测异常模式
   */
  private async detectAnomalyPattern(address: string, transactions: any[]): Promise<TransactionPattern[]> {
    const patterns: TransactionPattern[] = [];
    
    // 检测异常大额交易
    const amounts = transactions.map(tx => tx.valueUSD);
    const avgAmount = amounts.reduce((sum, amt) => sum + amt, 0) / amounts.length;
    const stdDev = Math.sqrt(amounts.reduce((sum, amt) => sum + Math.pow(amt - avgAmount, 2), 0) / amounts.length);
    
    const anomalousTransactions = transactions.filter(tx => 
      Math.abs(tx.valueUSD - avgAmount) > 2 * stdDev
    );

    if (anomalousTransactions.length > 0) {
      patterns.push({
        id: `anomaly_${Date.now()}`,
        type: 'anomaly',
        confidence: Math.min(anomalousTransactions.length / 3, 1),
        description: `检测到${anomalousTransactions.length}笔异常交易`,
        frequency: anomalousTransactions.length,
        avgAmount: anomalousTransactions.reduce((sum, tx) => sum + tx.valueUSD, 0) / anomalousTransactions.length,
        timePattern: this.extractTimePattern(anomalousTransactions),
        relatedAddresses: [...new Set([
          ...anomalousTransactions.map(tx => tx.from),
          ...anomalousTransactions.map(tx => tx.to)
        ])],
        detectedAt: new Date()
      });
    }

    return patterns;
  }

  /**
   * 生成行为洞察
   */
  public async generateBehaviorInsights(address: string, chain: ChainType): Promise<BehaviorInsight[]> {
    const insights: BehaviorInsight[] = [];
    const patterns = await this.analyzeTransactionPatterns(address, chain);
    
    for (const pattern of patterns) {
      const insight = await this.patternToInsight(address, pattern);
      if (insight) {
        insights.push(insight);
      }
    }

    return insights;
  }

  /**
   * 将模式转换为洞察
   */
  private async patternToInsight(address: string, pattern: TransactionPattern): Promise<BehaviorInsight | null> {
    const evidence: Evidence[] = [
      {
        type: 'pattern',
        description: pattern.description,
        data: pattern,
        weight: pattern.confidence
      }
    ];

    switch (pattern.type) {
      case 'deposit':
        return {
          id: `insight_${Date.now()}`,
          address,
          type: 'exchange_flow',
          title: '频繁充值行为',
          description: `该地址表现出频繁向交易所充值的行为，可能准备出售代币`,
          severity: pattern.frequency > 10 ? 'high' : 'medium',
          confidence: pattern.confidence,
          evidence,
          timestamp: new Date(),
          impact: {
            marketImpact: pattern.avgAmount > 1000000 ? 'major' : 'moderate',
            priceImpact: -0.01 * (pattern.avgAmount / 1000000)
          }
        };

      case 'withdrawal':
        return {
          id: `insight_${Date.now()}`,
          address,
          type: 'exchange_flow',
          title: '频繁提现行为',
          description: `该地址频繁从交易所提现，可能在建仓或转移资金`,
          severity: 'medium',
          confidence: pattern.confidence,
          evidence,
          timestamp: new Date()
        };

      case 'defi_interaction':
        return {
          id: `insight_${Date.now()}`,
          address,
          type: 'defi_farming',
          title: 'DeFi协议活跃用户',
          description: `该地址是DeFi协议的活跃用户，可能在进行流动性挖矿或借贷`,
          severity: 'low',
          confidence: pattern.confidence,
          evidence,
          timestamp: new Date()
        };

      case 'arbitrage':
        return {
          id: `insight_${Date.now()}`,
          address,
          type: 'whale_activity',
          title: '疑似套利交易',
          description: `检测到疑似套利交易模式，该地址可能是专业交易者`,
          severity: 'medium',
          confidence: pattern.confidence,
          evidence,
          timestamp: new Date()
        };

      case 'anomaly':
        return {
          id: `insight_${Date.now()}`,
          address,
          type: 'suspicious',
          title: '异常交易行为',
          description: `检测到异常交易模式，需要进一步关注`,
          severity: 'high',
          confidence: pattern.confidence,
          evidence,
          timestamp: new Date()
        };

      default:
        return null;
    }
  }

  /**
   * 检测异常告警
   */
  public async detectAnomalies(address: string, chain: ChainType): Promise<AnomalyAlert[]> {
    const alerts: AnomalyAlert[] = [];
    const recentTransactions = await this.dbService.getRecentTransactionsByAddress(address, chain, 24); // 24小时内
    
    if (recentTransactions.length === 0) return alerts;

    // 获取历史基线
    const historicalTransactions = await this.dbService.getTransactionsByAddress(address, chain);
    const baseline = this.calculateBaseline(historicalTransactions);

    // 检测异常交易量
    const recentVolume = recentTransactions.reduce((sum, tx) => sum + tx.valueUSD, 0);
    if (recentVolume > baseline.dailyVolume * 3) {
      alerts.push({
        id: `anomaly_${Date.now()}`,
        address,
        type: 'unusual_volume',
        severity: 'high',
        title: '异常交易量',
        description: `24小时内交易量异常，为历史平均值的${(recentVolume / baseline.dailyVolume).toFixed(1)}倍`,
        detectedAt: new Date(),
        threshold: baseline.dailyVolume * 3,
        actualValue: recentVolume,
        historicalBaseline: baseline.dailyVolume,
        recommendations: [
          '密切监控后续交易',
          '分析资金来源和去向',
          '检查是否与市场事件相关'
        ]
      });
    }

    return alerts;
  }

  /**
   * 提取时间模式
   */
  private extractTimePattern(transactions: any[]): any {
    const hours = transactions.map(tx => new Date(tx.timestamp).getHours());
    const days = transactions.map(tx => new Date(tx.timestamp).getDay());
    
    return {
      dayOfWeek: this.findFrequentValues(days),
      hourOfDay: this.findFrequentValues(hours),
      isRegular: this.calculateRegularity(transactions.map(tx => new Date(tx.timestamp)))
    };
  }

  /**
   * 查找频繁值
   */
  private findFrequentValues(values: number[]): number[] {
    const frequency = new Map<number, number>();
    values.forEach(val => {
      frequency.set(val, (frequency.get(val) || 0) + 1);
    });

    const threshold = values.length * 0.2;
    return Array.from(frequency.entries())
      .filter(([_, count]) => count > threshold)
      .map(([value, _]) => value);
  }

  /**
   * 计算规律性
   */
  private calculateRegularity(timestamps: Date[]): boolean {
    if (timestamps.length < 3) return false;

    const intervals = [];
    for (let i = 1; i < timestamps.length; i++) {
      intervals.push(timestamps[i].getTime() - timestamps[i-1].getTime());
    }

    const avgInterval = intervals.reduce((sum, interval) => sum + interval, 0) / intervals.length;
    const variance = intervals.reduce((sum, interval) => sum + Math.pow(interval - avgInterval, 2), 0) / intervals.length;
    
    const regularity = 1 - Math.sqrt(variance) / avgInterval;
    return regularity > 0.7; // 70%以上规律性认为是规律的
  }

  /**
   * 识别DeFi协议
   */
  private identifyDeFiProtocol(address: string): string {
    // 简化实现，根据地址识别协议
    const lowerAddr = address.toLowerCase();
    if (lowerAddr.includes('aave')) return 'Aave';
    if (lowerAddr.includes('compound')) return 'Compound';
    if (lowerAddr.includes('uniswap')) return 'Uniswap';
    return 'Unknown DeFi';
  }

  /**
   * 计算历史基线
   */
  private calculateBaseline(transactions: any[]): any {
    if (transactions.length === 0) {
      return { dailyVolume: 0, dailyCount: 0 };
    }

    const totalVolume = transactions.reduce((sum, tx) => sum + tx.valueUSD, 0);
    const totalDays = Math.max(1, (Date.now() - new Date(transactions[0].timestamp).getTime()) / (24 * 60 * 60 * 1000));
    
    return {
      dailyVolume: totalVolume / totalDays,
      dailyCount: transactions.length / totalDays
    };
  }

  /**
   * 清理缓存
   */
  public clearCache(): void {
    this.patternCache.clear();
    logger.debug('已清理模式识别缓存');
  }
} 